<?php

class MagicEnvelope {
	
	const NS = 'http://salmon-protocol.org/ns/magic-env';
	
	const ENCODING = 'base64url';
	const ALGORITH = 'RSA-SHA256';
	
	private $encodedData;
	private $decodedData;
	
	private $dataType;
	private $encoding;
	private $alg;
	private $signature;
	
	public static function build($encodedData, $signature) {
	    $magicEnv = new MagicEnvelope();
        $magicEnv->setEncodedData(trim($encodedData))
        		 ->setDataType("application/atom+xml")
        		 ->setEncoding(self::ENCODING)
        		 ->setAlg(self::ALGORITH)
        		 ->setSignature($signature)
        		 ->setDecodedData(Utils::base64_url_decode(trim($encodedData)));

		return $magicEnv;
	}
	
	public function asXML() {
	    $dom = new DOMDocument('1.0', 'UTF-8');
        $dom->formatOutput = true;
        
        $env_element = $dom->createElementNS('http://salmon-protocol.org/ns/magic-env', 'me:env');
        $dom->appendChild($env_element);
	    return $dom->saveXML();
	}
	
	/**
	 * We will have rawData input similar to this:
	 * 
	 * <?xml version="1.0"?>
	 * <me:env xmlns:me="http://salmon-protocol.org/ns/magic-env">
	 *    <me:data type="application/atom+xml">PD94bWwgdmVyc2lvbj0iMS ... [TURNCATED]</me:data>
	 *    <me:encoding>base64url</me:encoding>
	 *    <me:alg>RSA-SHA256</me:alg>
	 *    <me:sig>nMpL0rwJonpVMPG6TBJtEQCI5_-RBNrUNkxVs-yY99zMDMyoVmJ ... [TURNCATED]</me:sig>
	 * </me:env>';
	 * 
	 * @param DOMDocument $dom
	 * @return MagicEnvelope Returns real real real Magic Envelope
	 */
	public static function buildFromRawXML($rawXml) {
        $dom = new DOMDocument();
        if(@$dom->loadXML($rawXml)) {
            return self::buildFromDom($dom);
        }
        throw new Exception("Invalid raw XML data provided!");
	}
	
	public static function buildFromDom(DOMDocument $dom) {
		
		$env_element = $dom->getElementsByTagNameNS(MagicEnvelope::NS, 'env')->item(0);
        if (!$env_element) {
            $env_element = $dom->getElementsByTagNameNS(MagicEnvelope::NS, 'provenance')->item(0);
        }

        if (!$env_element) {
            //TODO Throw exception
        }

        $data_element = $env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'data')->item(0);
        
        $magicEnv = new MagicEnvelope();
        $magicEnv->setEncodedData(trim($data_element->nodeValue))
        		 ->setDataType($data_element->getAttribute('type'))
        		 ->setEncoding($env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'encoding')->item(0)->nodeValue)
        		 ->setAlg($env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'alg')->item(0)->nodeValue)
        		 ->setSignature($env_element->getElementsByTagNameNS(MagicEnvelope::NS, 'sig')->item(0)->nodeValue)
        		 ->setDecodedData(Utils::base64_url_decode(trim($data_element->nodeValue)));

		return $magicEnv;
	}
	
	private function setEncodedData($data){
		$this->encodedData = $data;
		return $this;
	}
	
	public function getEncodedData() {
		return $this->encodedData;
	}
	
	private function setDecodedData($data){
		$this->decodedData = $data;
		return $this;
	}
	
	private function setDataType($dataType){
		$this->dataType = $dataType;
		return $this;
	}
	
	private function setEncoding($encoding){
		$this->encoding = $encoding;
		return $this;
	}
	
	private function setAlg($alg){
		$this->alg = $alg;
		return $this;
	}
	
	private function setSignature($sig){
		$this->signature = $sig;
		return $this;
	}
	
	public function getSignature() {
		return $this->signature;
	}
	
	public function __toString()
    {
        return print_r(get_object_vars($this), true);
    }
}